


#include "asio.hpp"
#include "client.h"
#include "boost/array.hpp"
//#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/bind.hpp>

using asio::ip::tcp;
class ClientConn
: public boost::enable_shared_from_this<ClientConn>
{
    public:
        typedef boost::shared_ptr<ClientConn> pointer;

        static pointer create(asio::io_service& io_service)
        {
            return pointer(new ClientConn(io_service));
        }

        tcp::socket& socket()
        {
            return socket_;
        }
        void start( asio::io_service & ios)
        {
            //域名解析，只将域名解析为ipv4地址
            tcp::resolver resolver(ios);
            tcp::resolver::query query(tcp::v4(),"127.0.0.1", "8989");
            tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
            asio::error_code curerror;
            socket_.connect(*endpoint_iterator, curerror);   
            if (curerror){
                throw curerror;  

                printf("error!\n");
            }
            printf("connected\n");
            message_ = "11111111111111111111";
            asio::async_write(socket_, asio::buffer(message_),
                    boost::bind(&ClientConn::handle_write, shared_from_this(),
                        asio::placeholders::error,
                        asio::placeholders::bytes_transferred));

            printf("all setup\n");
        }

    private:
        ClientConn(asio::io_service& io_service)
            : socket_(io_service)
        {
            //memset( msg_, 0, 1024);
        }

        void handle_write(const asio::error_code&  error, size_t size)
        { 
            if ( error){
                printf( "error: %s\n" , error.message().c_str());
                return ;
            }
            if ( size == message_.length() ) {
                printf("finished write out\n");
                asio::async_read(socket_, msg_, asio::transfer_at_least(1),
                        boost::bind(&ClientConn::handle_read, shared_from_this(),
                            asio::placeholders::error,
                            asio::placeholders::bytes_transferred));
                printf("start reading\n");
            }
        }

        void handle_read(const asio::error_code& error, size_t size)
        { 
            if ( error){
                printf( "error: %s\n" , error.message().c_str());
                return ;
            }
            printf ( "got msg size: %d\n" , size);
            //printf ( "got msg: %s\n" , msg_ );
        }

        tcp::socket socket_;
        std::string message_;
        asio::streambuf msg_;
        //boost::array<char, 1024> msg_;
};


struct Client::Impl{
    asio::io_service _ios;
    public:
    Impl() {
        ClientConn::pointer _conn =  ClientConn::create(_ios) ;
        _conn->start( _ios);
    }
};


Client::Client(): _impl( new Impl() ){
}
Client::~Client(){
    delete _impl;
}

void Client::init(){
    _impl->_ios.run();
}


#ifdef UNIT_TEST
int main(){
    Client clt;
    clt.init();
    return 0;

}
#endif //UNIT_TEST
